home *** CD-ROM | disk | FTP | other *** search
/ SGI Hot Mix 17 / Hot Mix 17.iso / HM17_SGI / research / lib / efont.pro < prev    next >
Text File  |  1997-07-08  |  30KB  |  1,049 lines

  1. ; $Id: efont.pro,v 1.12 1997/01/15 03:11:50 ali Exp $
  2.  
  3. ; Copyright (c) 1992-1997, Research Systems, Inc.  All rights reserved.
  4. ;    Unauthorized reproduction prohibited.
  5.  
  6.  
  7. ; Color indices: 0 = black (background), 1 = white, 2 = red, 3 = green, 4 = blue
  8. ; fdraw, fwin = font drawable/window
  9. ; cdraw, cwin = character drawable/window
  10. ; mapped = 0 for font display, 1 for character display
  11. ; nchars = # of characters in current font.  Either = to 224 (256-32) or = to
  12. ;        96 = (128-32).
  13. ; cur_vects = vectors for current character
  14. ; chr_char = index of current char = (ascii - 32)    
  15.  
  16. PRO translate_vects, in, x, y, pen_up   ;Given packed vectors,
  17. ; return the X, Y, and Pen_up components.
  18.  
  19. x = ishft(in, -7) and 127    ;Get X and Y components
  20. y = in and 127
  21. neg = where(x and 64, count)
  22. if count gt 0 then x[neg] = x[neg]-128
  23. neg = where(y and 64, count)
  24. if count gt 0 then y[neg] = y[neg]-128
  25. pen_up = (in and 16384) ne 0        ;Pen up bit
  26. end
  27.  
  28.  
  29. PRO draw_char, x0, y0, siz, vects, color = c
  30. if vects[0] eq -1 then return  ;Anything?
  31. n = n_elements(vects)
  32. if (vects[0] and 16384) eq 0 then begin    ;Scale factor & offset?
  33.     s = vects[0]/500. * siz
  34.     off = vects[1]
  35.     st = 2
  36. endif else begin
  37.     s = siz
  38.     off = 0
  39.     st = 0
  40. endelse
  41.  
  42. translate_vects, vects, x, y, pen_up
  43.  
  44. if n_elements(c) le 0 then c = 1
  45. x = s * x + x0
  46. y = s * y + y0 + off
  47.  
  48. ;        Draw each segment
  49. start = [where(pen_up, count), n_elements(pen_up)]
  50. for i=0, count-1 do PLOTS, /DEVICE, COLOR=c, $
  51.     x[start[i]:start[i+1]-1], y[start[i]:start[i+1]-1]
  52. end
  53.  
  54.  
  55. PRO redraw, map        ;Map = 1 for chars, 0 for font
  56. common efont_com, unit, fonttab, nchars, chartab, vectors, fwin, cwin, fnum, $
  57.     fdraw, cdraw, cur_char, cur_chartab, cur_vects, cur_char_offset, $
  58.     cur_char_scale, chx, chy, x_0, y_0, sx, cpos_txt, cinfo_txt, $
  59.     cwidth_txt, coff_txt, cscale_txt, mapped, MAX_FONT, $
  60.     drag, prev, buttons, mask, fnum_txt, changed, $
  61.     dup_move, file_name, refresh_pixmap
  62.  
  63. if n_elements(map) gt 0 then begin
  64.     mapped = map
  65.     WIDGET_CONTROL, fdraw, MAP=map eq 0
  66.     WIDGET_CONTROL, cdraw, MAP=map eq 1
  67. endif
  68.     
  69. WIDGET_CONTROL, fnum_txt, SET_VALUE='Font '+strtrim(fnum,2)
  70. if mapped eq 0 then begin
  71.     wset, fwin
  72.     erase
  73.     draw_font
  74. endif else begin
  75.     wset, cwin
  76.     erase
  77.     draw_grid
  78. ;        vertical line on right in blue = width of character cell 
  79.     plots, sx * cur_chartab.width + x_0, [0, !d.y_size-1], $
  80.         color=4, /DEV, LINES=2
  81.     wset, refresh_pixmap[0]        ;Save the background
  82.     device, copy = [0, 0, !d.x_size, !d.y_size, 0, 0, cwin]
  83.     wset, cwin
  84.  
  85.     t = '"' + string(byte(cur_char)) + '" = ' + $
  86.        strtrim(cur_char,2) + '(10) '+ $
  87.         string(cur_char, format='(O3)') + '(8) ' +  $
  88.         string(cur_char, format='(Z2)') + '(16). ' + $
  89.         strtrim(n_elements(cur_vects), 2) + ' Vectors'
  90.  
  91.     if cur_vects[0] ne -1 then draw_char, x_0, y_0, sx, cur_vects
  92.     WIDGET_CONTROL, cinfo_txt, SET_VALUE = t
  93.     WIDGET_CONTROL, cwidth_txt, set_value=strtrim(fix(cur_chartab.width),2)
  94.     endelse
  95. END
  96.  
  97.  
  98.  
  99. PRO draw_font
  100. common efont_com
  101.  
  102. for i=0,15 do xyouts, (i+2)*chx, !d.y_size - chy, /DEV, siz=1.5, $
  103.     string(i, format='(z1)')
  104. for i= 2, (nchars+32)/16-1 do begin    ;Rows
  105.     y = !d.y_size - (i+0) * chy
  106.     xyouts, 0, y, /DEV, string(i, format='(z1)'), siz=1.5
  107.     for j=0, 15 DO BEGIN
  108.         c = i*16 + j
  109.         offset = chartab[c-32].offset
  110.         nv = chartab[c-32].nvecs
  111.         if nv ne 0 then begin
  112.         draw_char, (j+2) *chx, y, 1.0, vectors[offset : offset + nv-1]
  113.         endif
  114.         ENDFOR
  115.     ENDFOR
  116. END
  117.  
  118.  
  119. PRO draw_grid, color
  120. common efont_com
  121.  
  122. if n_elements(color) le 0 then color = 3
  123.  
  124. nx = !d.x_size / sx
  125. ny = !d.y_size / sx
  126. x_0 = (!d.x_size/2 - sx * 16 + sx-1)/sx * sx  ;Grid point of origin
  127. y_0 = (!d.y_size/2 - sx * 16 + sx-1)/sx * sx
  128. c = 3
  129.  
  130. if sx le 8 then dx = (16/sx) * sx else dx = sx
  131. for i=0,!d.x_size-1, dx do for j=0, !d.y_size-1, dx do $
  132.     plots, i, j, psym=1, color=c, /dev
  133. plots, [0, !d.x_size-1], [y_0, y_0], /DEV, color=2, lines=2
  134. plots, [x_0, x_0], [0, !d.y_size-1], /DEV, color=2, lines=2
  135. return
  136.  
  137. for i=0, !d.x_size-1, sx do begin
  138.     if (i-x_0 eq 0) or (i-x_0 eq 32*sx) then l = 2 else l = 1
  139.     plots, [i, i], [0, !d.y_size-1], /DEV, color = c, LINES=L
  140.     endfor
  141.  
  142. for i=0, !d.y_size-1, sx do begin
  143.     if (i-y_0 eq 0) or (i-y_0 eq 32*sx) then l=2 else l =1
  144.     plots, [0, !d.x_size-1], [ i, i],  /DEV, color = c, LINES=l
  145.     endfor
  146. end
  147.  
  148. PRO ADD_VECTOR, v0, v1        ;V0 and v1 are in screen coords..
  149. ; dup_move = 0 to add a vector, 1 to move a vector by v1-v0, and 2 to
  150. ;  move & duplicate.
  151. common efont_com
  152.  
  153.  
  154. x0 = FIX((v0[0] - x_0) / sx) and 127    ;To our coords
  155. x1 = FIX((v1[0] - x_0) / sx) and 127
  156. y0 = FIX((v0[1] - y_0) / sx) and 127
  157. y1 = FIX((v1[1] - y_0) / sx) and 127
  158.  
  159. if x0 eq x1 and y0 eq y1 then return    ;Nothing to add
  160. e0 = fix(ishft(x0, 7) + y0)        ;Encoded new vects
  161. e1 = fix(ishft(x1, 7) + y1)
  162.  
  163. if cur_vects[0] eq -1 then begin    ;No vectors yet
  164.     cur_vects = [ e0 + 16384, e1]
  165.     return
  166.     endif
  167.  
  168. if dup_move eq 0 then begin
  169.     cur_vects = [ cur_Vects, e0 + 16384, e1]  ;Dumb way
  170.     return
  171.     endif
  172.  
  173. translate_vects, cur_vects, x, y, pen_up    ;Disassemble
  174. case dup_move of
  175. 1:    BEGIN
  176.     x = x + (x1-x0)
  177.     y = y + (y1-y0)
  178.     ENDCASE
  179. 2:    BEGIN
  180.     x = [ x, x + (x1-x0)]
  181.     y = [ y, y + (y1-y0)]
  182.     pen_up = [pen_up, pen_up]
  183.     ENDCASE
  184. 3:    BEGIN
  185.     x = fix(x * float(x1)/float(x0) + 0.5)
  186.     y = fix(y * float(y1)/float(y0) + 0.5)
  187.     ENDCASE
  188. ENDCASE
  189. cur_vects = ishft(x and 127,7) + (y and 127) + 16384 * pen_up  ;Recombine
  190. dup_move = 0
  191. redraw
  192. end
  193.  
  194.  
  195. PRO Order_vectors, ctab, cvects
  196. ; Order the vectors for the character, combining where possible.
  197.  
  198. common efont_com
  199.  
  200. print,'Segments in  = ', fix(total((cvects and 16384) ne 0))
  201. merge_loop: 
  202.     n = n_elements(cvects)
  203.     bsegs = where((cvects and 16384) ne 0, count)    ;Beginning segments
  204.     if count lt 2 then goto, merge_done
  205.     esegs = [ bsegs[1:*] - 1, n-1]        ;Ending segments
  206.  
  207.     b = cvects[bsegs] and 16383
  208.     e = cvects[esegs]
  209.     for i=0, count-2 do for j=i+1,count-1 do begin    ;Dumb search
  210.     if b[i] eq e[j] then begin
  211.         v = [ cvects[bsegs[j]:esegs[j]], cvects[bsegs[i]+1:esegs[i]]]
  212.         goto, merge_vects
  213.         endif
  214.     if b[i] eq b[j] then begin 
  215.         v = [ reverse(cvects[bsegs[j]:esegs[j]]), $
  216.           cvects[bsegs[i]+1: esegs[i]]]
  217.         goto, merge_vects
  218.         endif
  219.     if e[i] eq e[j] then begin
  220.         v = [ cvects[bsegs[i]:esegs[i]], $
  221.         reverse(cvects[bsegs[j]: esegs[j]-1])]
  222.         goto, merge_vects
  223.         endif
  224.     if e[i] eq b[j] then begin
  225.         v = [ cvects[bsegs[i]:esegs[i]], cvects[bsegs[j]+1:esegs[j]]]
  226.     merge_vects: v = v and 16383    ;Mask off pen up bits
  227.         v[0] = v[0] or 16384    ;Pen up on first pnt
  228.         if count eq 2 then cvects = v $    ;Only two
  229.         else begin
  230.             k = replicate(1, n)
  231.             k[bsegs[j]:esegs[j]] = 0
  232.             k[bsegs[i]:esegs[i]] = 0
  233.             cvects = [ cvects[where(k)], v]    ;Combine
  234.         endelse
  235.         goto, merge_loop
  236.     endif
  237.     endfor
  238.  
  239. merge_done: ctab.nvecs = n_elements(cvects)
  240. print,'Segments out = ', fix(total((cvects and 16384) ne 0))
  241. end
  242.  
  243.  
  244. Function pnt_line, x0, y0, lx0, ly0, lx1, ly1
  245. ;  Return the perpendicular distance between the line thru (lx0, ly0)
  246. ;  and (lx1, ly1) and the point x0, y0.
  247. ; Add to that distance, the distance to the closest point if the 
  248. ; perpendicular is not on the line segment.
  249. p0 = float([x0, y0])
  250. p1 = [lx1, ly1]
  251. lu = [lx0, ly0]
  252.  
  253. lv = float(p1 - lu)
  254. l = sqrt(total(lv*lv))
  255. if l eq 0 then return, sqrt(total((lu-p0)^2))    ;Line is a point
  256. lv = lv / l
  257. ln = [ -lv[1], lv[0] ]
  258. lc = -total(ln * lu)
  259.  
  260. q = lc + total(ln * p0)
  261. q = p0 - q * ln        ;The point on the line....
  262.  
  263. d= (q - p1) * (q - lu)  ;Both are neg or 0 if on line..
  264. if d[0] gt 0 or d[1] gt 0 then begin
  265.     d1 = sqrt(total((p0-p1)^2))
  266.     d2 = sqrt(total((p0-lu)^2))
  267.     return, d1 < d2
  268.     endif
  269.  
  270. return, sqrt(total((p0 - q)^2))
  271. end
  272.  
  273.  
  274. PRO REMOVE_VECTOR, x0, y0        ;Remove the vector closest to x0,y0
  275. common efont_com
  276.  
  277. n = n_elements(cur_vects)
  278. if n le 2 then begin            ;Only one segment?
  279.     cur_vects = -1
  280.     goto, remove_done
  281.     endif
  282.  
  283. translate_vects, cur_vects, x, y, pen_up
  284. dmin = 1e6
  285.  
  286. for i=0, n-2 do $        ;Each vector
  287.     if pen_up[i+1] eq 0 then begin  ;dont do next vector
  288.     d = pnt_line(x0, y0, x[i], y[i], x[i+1], y[i+1])
  289.     if d lt dmin then begin
  290.         dmin = d
  291.         j = i
  292.         endif
  293.     endif            ;Pen up
  294.  
  295. first_seg = pen_up[j]
  296. if j eq n-2 then last_seg = 1 else last_seg = pen_up[j+2]
  297.  
  298. if first_seg and last_seg then to_remove = [j, j+1] $
  299. else if not (first_seg or last_seg) then $    ;Split
  300.     cur_vects[j+1] = cur_vects[j+1] + 16384 $
  301. else if first_seg then begin
  302.     to_remove = j            ;Remove first
  303.     cur_vects[j+1] = cur_vects[j+1] + 16384  ;and make 2nd first
  304. endif else to_remove = j+1        ;Remove last
  305.  
  306. if n_elements(to_remove) gt 0 then begin    ;Remove offending segs
  307.     good = replicate(1, n)       
  308.     good[to_remove] = 0
  309.     cur_vects = cur_vects[where(good)]
  310.     endif
  311.  
  312. remove_done:         ;Redraw background & then the char
  313. DEVICE, copy = [0, 0, !d.x_size, !d.y_size, 0, 0, refresh_pixmap[0]]
  314. draw_char, x_0, y_0, sx, cur_vects, color = xor_color
  315. end
  316.  
  317.  
  318. FUNCTION str_to_ccode, t    ;Return decimal, hex, or octal number
  319. ; Formats:  0nn Octal, 0xnn Hex, else Decimal
  320. if strmid(t,0,2) eq '0x' then begin    ;Hex
  321.     fmt = '(z8)'
  322.     t = strmid(t,2,100)
  323. endif else if strmid(t,0,1) eq '0' then fmt = '(o6)' $
  324. else fmt = '(i6)'
  325. on_ioerror, bad_num
  326. i = 0
  327. reads, t, i, format=fmt
  328. return, i
  329. bad_num:  junk = DIALOG_MESSAGE(['Invalid character code. Formats = ', $
  330.         '0xnn for hex, 0nn for octal, nnn for decimal'])
  331. return, -1        ;For error
  332. end
  333.  
  334.  
  335.  
  336. PRO VIEW_EVENT, event        ;Events from the view only base
  337.  
  338. if event.press ne 0 then begin
  339.     WIDGET_CONTROL, event.top, /DESTROY
  340. endif else begin
  341.     widget_control, event.top, get_uvalue=t    ;Get parameters
  342.     x = event.x - t[2]
  343.     y = event.y - t[3]
  344.     z = t[1]            ;zoom factor
  345.     if x lt 0 then x = (x - z/2) / z $   ;Round in proper direction
  346.     else x = (x + z/2) / z
  347.     if y lt 0 then y = (y - z/2) / z $
  348.     else y = (y + z/2) / z
  349.     WIDGET_CONTROL, t[0], set_value=strtrim(x,2) + ', '+strtrim(y,2)
  350. endelse
  351. end
  352.  
  353.  
  354. PRO CMODE_EVENT, event        ;For character editor window
  355. common efont_com
  356.  
  357. if event.id eq cdraw then begin
  358.     x = ROUND((event.x - x_0)/ float(sx))
  359.     y = ROUND((event.y - y_0)/ float(sx))
  360.  
  361.     WIDGET_CONTROL, cpos_txt, set_value=strtrim(x,2) + ', '+strtrim(y,2)
  362.     this = sx * [x,y] + [x_0, y_0]  ;Screen coords
  363.     if event.press eq 1 then begin  ;Initiate dragging a vector
  364.         drag = this
  365.         prev = drag
  366.         buttons = 1
  367.         wset, refresh_pixmap[1]        ;Save the background
  368.         device, copy = [0, 0, !d.x_size, !d.y_size, 0, 0, cwin]
  369.         wset, cwin
  370.         return
  371.         endif
  372.     if event.release eq 1 then begin  ;Done dragging a vector...
  373.         add_vector, drag, this
  374.         buttons = 0
  375.         changed = 1
  376.         return
  377.         endif
  378.     if buttons ne 0 then begin
  379.         if (this[0] eq prev[0]) and (this[1] eq prev[1]) THEN RETURN
  380.         if prev[0] ne drag[0] or prev[1] ne drag[1] then $
  381.           DEVICE, copy = [0, 0, !d.x_size, !d.y_size, $
  382.             0, 0, refresh_pixmap[1]]
  383.           plots, [drag[0], this[0]], [drag[1], this[1]], /DEV, color = 1
  384.           prev = this
  385.           endif        ;Buttons
  386.     if event.press ge 2 then begin        ;Middle or right B. to remove
  387.         if cur_vects[0] eq -1 then return    ;Nothing to remove...
  388.         changed = 1
  389.         remove_vector, x, y
  390.         endif        ;Remove
  391.     RETURN
  392. ENDIF
  393.  
  394. WIDGET_CONTROL, event.id, GET_UVALUE = eventval
  395.  
  396. dup_move = 0
  397. CASE eventval of
  398. "CCODE": BEGIN        ;Formats:  0nn Octal, 0xnn Hex, else Decimal
  399.     WIDGET_CONTROL, cinfo_txt, GET_VALUE=t
  400.     i = str_to_ccode(t[0])
  401.     if i lt 32 or i ge (nchars+32) then return
  402.     cur_char = i
  403.     changed = 1
  404.     cur_chartab = chartab[i-32]
  405.     redraw
  406.     return
  407.     ENDCASE
  408. "SCHAR": BEGIN            ;Replace char in font
  409. schar0: changed = 0
  410.     save_char, cur_char, cur_chartab, cur_vects
  411.     redraw, 0
  412.     ENDCASE
  413. "SHRINK": dup_move = 3
  414. "DMOVE": dup_move = 2
  415. "MOVE":  dup_move = 1
  416. "WIDTH": BEGIN
  417.     WIDGET_CONTROL, cwidth_Txt, GET_VALUE=t
  418.     cur_chartab.width = fix(t[0])
  419.     REDRAW, 1
  420.     ENDCASE
  421. "REDRAW": redraw
  422. "VIEW": BEGIN
  423.     if changed then begin
  424.         i = DIALOG_MESSAGE('Saved changes to character?', /QUESTION)
  425.         if i then goto, schar0
  426.         endif
  427.     redraw, 0
  428.     ENDCASE
  429. else:  print, eventval
  430. ENDCASE
  431. END
  432.     
  433. PRO save_char, cindex, ctab, cvects        ;Save character whose
  434. ;  code is cindex, whose struct is ctab, and whose vectors are cvects
  435. ;  in the current font.
  436.  
  437. common efont_com
  438.  
  439. if cur_char lt 32 then return
  440. c = cindex - 32
  441.  
  442. offset = chartab[c].offset        ;Old beginning
  443. iend = fix(chartab[c].nvecs) + offset    ;Old end
  444.  
  445. if cvects[0] eq -1 then begin        ;Removed character?
  446.     ctab.nvecs = 0        ;No vectors
  447.     if offset ne iend then begin    ;Remove old?
  448.     good = replicate(1,n_elements(vectors))
  449.     good[offset:iend-1] = 0
  450.     vectors = vectors[where(good)]
  451.     endif        
  452.     goto, schar1
  453.     endif
  454.         ;Adding a non-zero length character.....
  455. order_vectors, ctab, cvects        ;Combine where possible
  456. if offset ne 0 then t = [ vectors[0:offset-1], cvects ] $
  457. else t = cvects
  458. if iend ne n_elements(vectors) then vectors = [t, vectors[iend:*] ] $
  459. else vectors = t
  460.  
  461. schar1: ctab.offset = offset
  462.  chartab[c] = ctab
  463.  for i=c+1, n_elements(chartab)-1 do $    ;Re-align other chars
  464.     chartab[i].offset = chartab[i-1].offset + fix(chartab[i-1].nvecs)
  465. end
  466.  
  467.  
  468.  
  469. PRO save_font, unit, fonttab, index, vectors, chartab
  470.  
  471. MAX_FONT = 40
  472. mask = '7fffffff'xl
  473. nchars = n_elements(chartab)
  474. point_lun, unit, 0
  475.  
  476. k = 320                ;Starting offset in each file
  477. f = fonttab            ;New font table
  478. save = 0
  479. for i=0, MAX_FONT-1 do begin    ;Re-arrange each font
  480.     if i eq index then begin    ;This font?
  481.     l = n_elements(vectors) * 2 ;Length in bytes of vectors
  482.     k0 = k            ;Where we write
  483.     f[0,i] = k0        ;Where we start
  484.     if nchars eq 224 then f[1,i] = l or (not mask) $
  485.     else f[1,i] = l
  486.     endif
  487.     if f[0,i] eq -1 then l = 0 else begin  ;Length
  488.         l = f[1,i] and mask        ;# of bytes in vects
  489.         if (f[1,i] and (not mask)) ne 0 then l = 4 * 224 + l $
  490.     else l = 4 * 96 + l
  491.     f[0,i] = k        ;Starting pos
  492.     if (i gt index) and save eq 0 then $  ;What we have to save
  493.         save = fonttab[0,i]     ;Where we read
  494.     endelse
  495.     k = k + l
  496. endfor
  497.  
  498. byteorder, f, /HTONL            ;To Network order
  499. writeu, unit, f                ;The fonttable
  500. byteorder, f, /NTOHL            ;& Back again
  501.  
  502. if save ne 0 then begin            ;Save following fonts
  503.     point_lun, unit, save
  504.     big = max(fonttab[0,*], last)    ;Get # of bytes in file
  505.     big = big + (fonttab[1,last] and mask)    ;Last byte + 1 of file
  506.     temp = bytarr(big-save, /nozero)
  507.     readu, unit, temp
  508.     endif
  509. point_lun, unit, k0            ;Where we write
  510. off = chartab.offset            ;Offsets of characters
  511. byteorder, off, /HTONS            ;To network order
  512. tc = chartab
  513. tc.offset = off
  514.  
  515. byteorder, vectors, /HTONS        ;To network ordering
  516. writeu, unit, tc, vectors        ;Write our font
  517. byteorder, vectors, /NTOHS        ;& Back to host
  518.  
  519. if save ne 0 then writeu, unit, temp    ;Following fonts    
  520. fonttab = f                ;New font table
  521. print, 'Saved font', index, ' at:', k0
  522. end
  523.  
  524.  
  525. PRO cload_proc, event
  526. common efont_com
  527.  
  528. WIDGET_CONTROL, event.id, GET_UVALUE=b
  529. if n_elements(b) le 0 then return
  530.  
  531. a = event.top            ;Top level widget
  532. WIDGET_CONTROL, a, GET_UVALUE=u    ;Widget ID's of text widgets....
  533. WIDGET_CONTROL, u[0], GET_VALUE=Fnum_T
  534. index = str_to_ccode(Fnum_t[0])    ;Font index
  535. ;   if index lt 0 or index ge MAX_FONT then return
  536. if index lt 3 or index ge 30 then return
  537.  
  538. CASE b of 
  539. "CLOAD": BEGIN
  540.     changed = 1
  541.     WIDGET_CONTROL, u[1], GET_VALUE=Cnum_T
  542.     ccode = str_to_ccode(Cnum_t[0])
  543.     if ccode lt 32 then return
  544.     read_font, index, fonttab, unit, n, c, v    ;Read the font
  545.     if n_elements(c) le 1 then return
  546.     if ccode lt 32 or (ccode-32) ge n then goto, bad_code
  547.     old_offset = cur_chartab.offset        ;Prev char
  548.     cur_chartab = c[ccode-32]
  549.     offset = cur_chartab.offset
  550.     cur_chartab.offset = old_offset        ;Vectors of current char
  551.     nv = fix(cur_chartab.nvecs)
  552.     if nv gt 0 then cur_vects = v[offset : offset + nv-1] $
  553.     else cur_vects = -1
  554.     redraw, 1
  555.     WIDGET_CONTROL, cwidth_txt, SET_VALUE=STRTRIM(FIX(cur_chartab.width),2)
  556.     WIDGET_CONTROL, coff_txt, SET_VALUE=STRTRIM(cur_char_offset,2)
  557.     WIDGET_CONTROL, cscale_txt, SET_VALUE=STRTRIM(cur_char_scale)
  558.     ENDCASE
  559. "CVIEW": BEGIN            ;View a character in a new window
  560.     WIDGET_CONTROL, u[1], GET_VALUE=Cnum_T
  561.     ccode = str_to_ccode(Cnum_t[0])
  562.     if ccode lt 32 then return
  563.     read_font, index, fonttab, unit, n, c, v    ;Read the font
  564.     if n_elements(c) le 1 then return
  565.     if ccode lt 32 or (ccode-32) ge n then goto, bad_code
  566.     a = WIDGET_BASE(Title='Font '+strtrim(index,2) + ' Char = ' + $
  567.         string(byte(ccode)), /COLUMN)
  568.     t = WIDGET_TEXT(a, xsize=30, ysize=1)
  569.     b = WIDGET_DRAW(a, xsize=!d.x_size, ysize = !d.y_size, /BUTTON, $
  570.         EVENT_PRO = 'VIEW_EVENT', /MOTION)
  571.     c = c[ccode-32]            ;The char
  572.     if c.nvecs eq 0 then return    ;Nothing there
  573.  
  574.     widget_control, a, /realize
  575.     widget_control, b, get_value= pwin    ;Preview window
  576.     WIDGET_CONTROL, a, SET_UVALUE=[t, sx, x_0, y_0]    ;Save the text widget
  577.     draw_grid
  578.     plots, [1,1] * sx * c.width + x_0, [0, !d.y_size-1], $
  579.         color=4, /DEV, LINES=2
  580.     draw_char, x_0, y_0, sx, v[c.offset: c.offset+c.nvecs -1]
  581.     wset, cwin
  582.     ENDCASE
  583. "FLOAD": BEGIN
  584.     changed = 0
  585.     if fonttab[0,index] eq -1 then goto, bad_code
  586.     read_font, index, fonttab, unit, nchars, chartab, vectors
  587.     fnum = index
  588.     redraw, 0
  589.     ENDCASE
  590. "FSAVE": BEGIN
  591.     changed = 0
  592.     if n_elements(vectors) le 1 then begin
  593.         del = DIALOG_MESSAGE('Current font has no characters')
  594.         goto, done
  595.         endif
  596.     close, unit
  597.     openu, unit, file_name
  598.     save_font, unit, fonttab, index, vectors, chartab
  599.     redraw, 0
  600.     fnum = index
  601.     ENDCASE
  602. ENDCASE
  603.  
  604. done: WIDGET_CONTROL, event.top, /destroy    ;All done
  605. return
  606.  
  607. bad_code:  junk = DIALOG_MESSAGE("Invalid character or font code.")
  608. return
  609. end
  610.  
  611.  
  612.  
  613.  
  614. PRO rw_font_char, charflg, writeflg    ;Read/write a single character
  615. ;        from font file.
  616.  
  617. common efont_com
  618.  
  619. name = (['Font', 'Character'])[charflg]
  620. ierr = 0
  621.  
  622. open_again: a = widget_base(Title='Read/Write Individual '+ name, /COLUMN)
  623. if ierr ne 0 then junk = WIDGET_LABEL(a, VALUE=f[0] + ' not found.')
  624. a0 = WIDGET_BASE(a, /row)
  625. junk = WIDGET_LABEL(a0, VALUE='File Name: ')
  626. b = WIDGET_TEXT(a0, /EDIT, xsize=20, ysize=1, /FRAME, UVALUE='OK')
  627. junk = WIDGET_BUTTON(a, VALUE='Cancel', UVALUE='CANCEL')
  628. WIDGET_CONTROL, a, /REAL
  629. event = WIDGET_EVENT(a)
  630. WIDGET_CONTROL, event.id, GET_UVALUE=t
  631.  
  632. IF t EQ "CANCEL" THEN BEGIN
  633.     WIDGET_CONTROL, a, /DESTROY
  634.     return
  635.     ENDIF
  636.  
  637. WIDGET_CONTROL, b, GET_VALUE=f
  638. WIDGET_CONTROL, a, /DESTROY
  639.  
  640. if charflg then begin
  641.     if writeflg then begin    ;Save character
  642.     openw, unit1, /GET_LUN, f[0], /XDR
  643.     writeu, unit1, cur_chartab
  644.     nv = fix(cur_chartab.nvecs)
  645.     offset = cur_chartab.offset
  646.     if nv gt 0 then v = vectors[offset: offset + nv-1] else v = -1
  647.     writeu, unit1, v
  648.     endif else begin        ;Read character
  649.     print,'read'
  650.     openr, unit1, /GET_LUN, f[0], /XDR, ERROR=ierr
  651.     if ierr ne 0 then goto, open_again
  652.     readu, unit1, cur_chartab
  653.     nv = fix(cur_chartab.nvecs)
  654.     cur_vects = intarr(nv, /NOZERO)
  655.     readu, unit1, cur_Vects
  656.     save_char, cur_char, cur_chartab, cur_vects
  657.     endelse
  658.     redraw, 1
  659. endif else begin        ;Fonts....
  660.     if writeflg then begin
  661.     openw, unit1, /GET_LUN, f[0], /XDR
  662.     writeu, unit1, n_elements(chartab), n_elements(vectors)
  663.     writeu, unit1, chartab
  664.     writeu, unit1, vectors
  665.     endif else begin        ;Read a font...
  666.     openr, unit1, /GET_LUN, f[0], /XDR, ERROR=ierr
  667.     if ierr ne 0 then goto, open_again
  668.     nc = 0L
  669.     nv = 0L
  670.     readu, unit1, nc, nv
  671.     chartab = replicate({CTAB}, nc)
  672.     readu, unit1, chartab
  673.     vectors = intarr(nv, /NOZERO)
  674.     readu, unit1, vectors
  675.     nchars = nc
  676.     endelse
  677.     redraw, 0
  678. endelse
  679.  
  680. free_lun, unit1
  681. end
  682.  
  683.  
  684. PRO efont_event, event
  685. common efont_com
  686.  
  687. WIDGET_CONTROL, event.top, /HOURGLASS
  688.  
  689. swin = !D.WINDOW
  690.  
  691. if event.id eq fdraw then begin        ;Select a character?
  692.     if event.press ne 0 then goto, clean_exit
  693.     x = (event.x) / chx - 2
  694.     y = (!d.y_size - event.y ) / chy + 1
  695.     if (x lt 0) or (x gt 15) or $
  696.         (y lt 2) or (y ge (nchars+32)/16) then goto, clean_exit
  697.     cur_char = x + y * 16
  698.     cur_chartab = chartab[cur_char-32]
  699.     offset = cur_chartab.offset   ;Vectors of current char
  700.     WIDGET_CONTROL, cwidth_txt, SET_VALUE=STRTRIM(FIX(cur_chartab.width),2)
  701.     WIDGET_CONTROL, coff_txt, SET_VALUE=STRTRIM(cur_char_offset,2)
  702.     WIDGET_CONTROL, cscale_txt, SET_VALUE=STRTRIM(cur_char_scale)
  703.     nv = fix(cur_chartab.nvecs)
  704.     if nv gt 0 then cur_vects = vectors[offset : offset + nv-1] $
  705.     else cur_vects = -1
  706.     redraw, 1
  707.     goto, clean_exit
  708.     endif
  709.  
  710. dup_move = 0
  711. WIDGET_CONTROL, event.id, GET_UVALUE = eventval
  712.  
  713. IF STRMID(eventval, 0, 1) eq '@' THEN BEGIN
  714.     junk = execute(strmid(eventval, 1, 100))
  715.     goto, clean_exit
  716.     ENDIF
  717.  
  718. CASE eventval of
  719. "SET8":  BEGIN
  720.     if nchars eq 224 then goto, clean_exit
  721.     nchars = 224
  722.     t = chartab[0]
  723.     t.nvecs = 0
  724.     t.width = 16
  725.     t.offset = chartab[95].offset
  726.     chartab = [ chartab, replicate(t, 128) ]
  727.     help, chartab
  728.     if mapped eq 0 then redraw
  729.     ENDCASE
  730.  
  731. ; "XLOAD": BEGIN
  732. ;     window, /free, /pix, xsize=128, ysize=128
  733. ;     siz = '720'
  734. ;     device, font='-monotype-gill sans-medium-r-normal-sans-0-' + siz + $
  735. ;         '-75-75-*'
  736. ;     xyouts, 64, 64, /DEV, string(byte(cur_char)), /FONT, COLOR=xor_color
  737. ;     device, font = 'fixed'
  738. ;     a = tvrd()
  739. ;     wdelete
  740. ;     redraw, 1
  741. ;     zoom = 7
  742. ;     device, SET_GRAPHICS=6        ;Xor mode
  743. ;     tv, rebin(a, 128*zoom, 128*zoom), x_0-(64*zoom), y_0-(64*zoom)
  744. ;     device, SET_GRAPHICS=3
  745. ;     ENDCASE
  746.  
  747. "CVIEW": BEGIN
  748.     uv = "CVIEW"    
  749.     goto, cload_cview
  750.     ENDCASE
  751. "CLOAD": BEGIN        ;Load a character from another font....
  752.     uv = "CLOAD"
  753. cload_cview:    a = WIDGET_BASE(TITLE='Load Hershey character', $
  754.                 /COLUMN, GROUP_LEADER=event.top, /MODAL)
  755.     junk = widget_base(a, /row)
  756.     junk1 = WIDGET_LABEL(junk, VALUE = 'Font Number:')
  757.     font_t = WIDGET_TEXT(junk, XSIZE=8, YSIZE=1, /EDIT, $
  758.         VALUE=STRTRIM(fnum,2))
  759.     junk = widget_base(a, /row)
  760.     junk1 = WIDGET_LABEL(junk, VALUE = 'Character Code:')
  761.     char_t = WIDGET_TEXT(junk, XSIZE=8, YSIZE=1, /EDIT)
  762.     junk = WIDGET_BUTTON(a, VALUE="OK", UVALUE=uv)
  763.     WIDGET_CONTROL, a, /REALIZE, SET_UVALUE=[font_t, char_t]
  764.     XMANAGER, 'LoadBox', a, EVENT_HANDLER='CLOAD_PROC'
  765.     changed = 1
  766.     ENDCASE
  767.  
  768. "SCHAR":  rw_font_char, 1, 1        ;rw_font_char, char_flag, write_flag
  769. "SFONT":  rw_font_char, 0, 1
  770. "RCHAR":  rw_font_char, 1, 0
  771. "RFONT":  rw_font_char, 0, 0
  772.  
  773. "FLOAD": BEGIN
  774.     a = WIDGET_BASE(TITLE="Load Font", /COLUMN, $
  775.                         GROUP_LEADER=event.top, /MODAL)
  776.     t = "FLOAD"
  777. get_font_num:
  778.     junk = widget_base(a, /row)
  779.     junk1 = WIDGET_LABEL(junk, VALUE = 'Font Number:')
  780.     font_t = WIDGET_TEXT(junk, XSIZE=8, YSIZE=1, /EDIT, $
  781.         VALUE=strtrim(fnum,2))
  782.     junk = WIDGET_BUTTON(a, VALUE="OK", UVALUE=T)
  783.     WIDGET_CONTROL, a, /REALIZE, SET_UVALUE=[font_t, 0]
  784.     changed = 0
  785.     XMANAGER, 'LoadBox', a, EVENT_HANDLER='CLOAD_PROC'
  786.     ENDCASE
  787. "HELP" : XDisplayFile, FILEPATH("efont.txt", subdir=['help', 'widget']), $
  788.                 TITLE = "EFONT Help", $
  789.                 GROUP = event.top, $
  790.                 WIDTH = 72, HEIGHT = 24
  791. "SAVE":    BEGIN
  792.     a = WIDGET_BASE(TITLE="Save Font", /COLUMN)
  793.     t = "FSAVE"
  794.     goto, get_font_num
  795.     ENDCASE
  796. "DONE":  BEGIN
  797. ;    save_font_file
  798. bail_out: FREE_LUN, unit
  799.     WIDGET_CONTROL, event.top, /DESTROY
  800.     WDELETE, refresh_pixmap[0], refresh_pixmap[1]
  801.     ENDCASE
  802. ;"CANCEL":  goto, bail_out
  803. ELSE: help, eventval
  804. ENDCASE
  805.  
  806. clean_exit:
  807.   if (!D.WINDOW ne SWIN) THEN WSET, SWIN
  808. end
  809.  
  810.  
  811. pro read_font, index, fonttab, unit, nchars, ctab, vects
  812. ; Read the font numbered index from the open unit.  (We assume a font table
  813. ;  of 40 elements.)  Return
  814.  
  815.  
  816. nfonts = n_elements(fonttab)/2
  817. if nfonts lt 1 then begin        ;Read fonttab?
  818.     nfonts = 40
  819.     fonttab = lonarr(2, nfonts)    ;Get font directory
  820.     point_lun, unit, 0
  821.     readu, unit, fonttab
  822.     byteorder, fonttab, /NTOHL    ;To our order
  823.     endif
  824.  
  825. if index lt 0 or index ge nfonts then begin
  826.     junk = DIALOG_MESSAGE('Font index must be in range of 0 to '+ $
  827.         string(nfonts))
  828.     return
  829.     endif
  830.  
  831. if fonttab[0,index] eq -1 then begin
  832.     junk = DIALOG_MESSAGE('Font ' + string(index) + ' does not exist')
  833.     return
  834.     endif
  835.  
  836. ; Top bit set of fonttab(1,i) = 224 character set.
  837. mask = '7fffffff'xl
  838. if (fonttab[1,index] and (not mask)) ne 0 then nchars = 256-32 else $
  839.     nchars = 128-32
  840.  
  841. len = fonttab[1, index] and mask
  842. ctab = replicate({CTAB, nvecs: 0b, width: 0b, offset: 0}, nchars)
  843.  
  844. point_lun, unit, fonttab[0,index] and '0fffffff'xl    ;Beginning of font
  845. readu, unit, ctab        ;Read font table
  846. k = 0                ;Current offset
  847. for i=0, nchars-1 do begin    ;Un swap shorts
  848.     j = ctab[i].offset
  849.     byteorder, j, /NTOHS
  850.     if j eq 0 then j = k $    ;Put empty chars in their proper place
  851.     else if j ne k then print,'Inconsistent vector offset/length, chr = ',$
  852.         i+32
  853.     ctab[i].offset = j
  854.     k = k + fix(ctab[i].nvecs)
  855.     endfor
  856.  
  857. vects = intarr(len/2)        ;Read the vectors
  858. on_ioerror, bad
  859. readu, unit, vects
  860. bad: byteorder, vects, /NTOHS
  861. end
  862.  
  863.  
  864. PRO efont, init_font, FILE=file, GROUP = GROUP
  865. ;+
  866. ; NAME:
  867. ;    EFONT
  868. ;
  869. ; PURPOSE:
  870. ;    This widget provides a vector font editor and display.
  871. ;
  872. ; CATEGORY:
  873. ;    Fonts.
  874. ;
  875. ; CALLING SEQUENCE:
  876. ;    EFONT, Init_font
  877. ;
  878. ; INPUTS:
  879. ;    Init_font: The initial font index, from 3 to 29.  Default = 3.
  880. ;
  881. ; KEYWORD PARAMETERS:
  882. ;    GROUP:  The widget group, if part of a hierarchy.
  883. ;    FILE:    alternate font file name/path.  Use this if you don't want
  884. ;        to modify the standard font file.
  885. ;
  886. ; OUTPUTS:
  887. ;    No explicit outputs.
  888. ;
  889. ; COMMON BLOCKS:
  890. ;    efont_com.
  891. ;
  892. ; SIDE EFFECTS:
  893. ;    Reads and modifies the vector font file, which is normally
  894. ;    hersh1.chr in the IDL resource/fonts directory.
  895. ;
  896. ; RESTRICTIONS:
  897. ;    A basic editor.
  898. ;
  899. ; PROCEDURE:
  900. ;    Call EFONT and press the HELP button for instructions.
  901. ;
  902. ; MODIFICATION HISTORY:
  903. ;    DMS    Nov, 1992.
  904. ;    WSO, 1/95, Updated for new directory structure
  905. ;    DMS, May, 1996.  Removed device dependencies, updated to newer widgets.
  906. ;-
  907.  
  908.  
  909.  
  910. common efont_com
  911.  
  912. if XRegistered('efont') ne 0 THEN RETURN
  913.  
  914. swin = !D.window
  915. MAX_FONT = 40            ;# of fonts in header
  916. zooms = [ 4, 8,12, 16, 20]    ;Zoom factors...
  917. chx = 32            ;Char cell sizes
  918. chy = 32
  919. sx = 16                ;Zoom factor
  920. x_0 = 50
  921. y_0 = 50
  922. mapped = 0
  923. cur_char = 32
  924. cur_char_scale = 1
  925. cur_char_offset = 0
  926. buttons = 0
  927. changed = 0
  928. mask = '7fffffff'xl         ;Low bits for file start
  929. dup_move = 0
  930. if n_elements(init_font) gt 0 then fnum = init_font else fnum = 3
  931.  
  932. if n_elements(file) eq 0 then $
  933.     file_name = FILEPATH("hersh1.chr", subdir=['resource', 'fonts']) $
  934. else file_name = file
  935.  
  936. openr, unit, file_name, /GET_LUN, ERROR=i
  937. if i ne 0 then begin
  938.     junk = DIALOG_MESSAGE(['Could not read: '+file, !ERR_STRING])
  939.     return
  940.     endif
  941.  
  942. readu, unit, fonttab
  943. byteorder, fonttab, /NTOHL    ;To our order
  944.  
  945. main_base = WIDGET_BASE(Title='Hershey Font Editor', /COLUMN)
  946. ; Setting the managed attribute indicates our intention to put this app
  947. ; under the control of XMANAGER, and prevents our draw widgets from
  948. ; becoming candidates for becoming the default window on WSET, -1. XMANAGER
  949. ; sets this, but doing it here prevents our own WSETs at startup from
  950. ; having that problem.
  951. WIDGET_CONTROL, /MANAGED, main_base
  952.  
  953. top_line = WIDGET_BASE(main_base, /ROW)
  954.  
  955. junk = WIDGET_BUTTON(top_line, /NO_REL, VALUE='Done', UVALUE='DONE')
  956. junk = WIDGET_BUTTON(top_line, /MENU, VALUE='File')
  957. junk1 = WIDGET_BUTTON(junk, /NO_REL, VALUE='Save Character', UVALUE='SCHAR')
  958. junk1 = WIDGET_BUTTON(junk, /NO_REL, VALUE='Save Font', UVALUE='SFONT')
  959. junk1 = WIDGET_BUTTON(junk, /NO_REL, VALUE='Read Character', UVALUE='RCHAR')
  960. junk1 = WIDGET_BUTTON(junk, /NO_REL, VALUE='Read Font', UVALUE='RFONT')
  961. ; junk = WIDGET_BUTTON(top_line, /NO_REL, VALUE='Cancel', UVALUE='CANCEL')
  962. junk = WIDGET_BUTTON(top_line, /NO_REL, VALUE='Help', Uvalue = 'HELP')
  963. junk = WIDGET_BUTTON(top_line, /NO_REL, VALUE='Save Font', UVALUE='SAVE')
  964. junk = WIDGET_BUTTON(top_line, /MENU, VALUE='Load')
  965. junk1 = WIDGET_BUTTON(junk, VALUE='Font', UVALUE="FLOAD")
  966. junk1 = WIDGET_BUTTON(junk, VALUE='Character', UVALUE="CLOAD")
  967. junk1 = WIDGET_BUTTON(junk, VALUE='Character, View Only', UVALUE="CVIEW")
  968. ;;; junk1 = WIDGET_BUTTON(junk, VALUE='Preview X font', UVALUE='XLOAD')
  969.  
  970. junk = WIDGET_BASE(top_line, /ROW, /FRAME)
  971. junk1 = WIDGET_LABEL(junk, value = 'Zoom:')
  972. junk1 = WIDGET_BASE(junk, /EXCLUSIVE, /ROW)
  973. for i=0, n_elements(zooms)-1 do BEGIN
  974.     junk2 = WIDGET_BUTTON(junk1, VALUE=strtrim(zooms[i],2), $
  975.     UVALUE = '@sx='+strtrim(zooms[i],2) + '& if mapped then redraw',$
  976.          /NO_REL)
  977.     if zooms[i] eq sx then WIDGET_CONTROL, junk2, /SET_BUTTON    ;Set default
  978.     ENDFOR
  979. junk = WIDGET_BUTTON(top_line, VALUE='Set 8 bits', UVALUE='SET8', /NO_REL)
  980. fnum_txt = WIDGET_TEXT(top_line, value='Font '+strtrim(fnum,2), $
  981.         /FRAME, XSIZE=8)
  982.  
  983.  
  984. read_font, fnum, fonttab, unit, nchars, chartab, vectors ;Init font
  985. cur_chartab = chartab[32]        ;Any char will do
  986.  
  987. base = WIDGET_BASE(main_base)
  988. wbases = lonarr(2)
  989. wbases[0] = WIDGET_BASE(base, /COLUMN)
  990. wbases[1] = WIDGET_BASE(base, /COLUMN, EVENT_PRO = 'CMODE_EVENT')
  991. fdraw = WIDGET_DRAW(wbases[0], XSIZE = 640, YSIZE = 640, RETAIN=2, /BUTTON)
  992.  
  993. c_row = WIDGET_BASE(wbases[1], /ROW)
  994. ; Save
  995. ; Save as
  996. ; Load character
  997. ; Draw character
  998. junk = WIDGET_BUTTON(c_row, VALUE="View Font", UVALUE="VIEW", /NO_REL)
  999. junk = WIDGET_BUTTON(c_row, VALUE="Redraw", UVALUE="REDRAW", /NO_REL)
  1000. junk = WIDGET_BUTTON(c_row, VALUE="Save", UVALUE="SCHAR", /NO_REL)
  1001. junk = WIDGET_BUTTON(c_row, VALUE= 'Move/Scale', /MENU)
  1002. junk1 = WIDGET_BUTTON(junk, VALUE='Move', UVALUE='MOVE', /NO_REL)
  1003. junk1 = WIDGET_BUTTON(junk, VALUE='Move & Duplicate', UVALUE='DMOVE', /NO_REL)
  1004. junk1 = WIDGET_BUTTON(junk, VALUE='Scale', UVALUE='SHRINK', /NO_REL)
  1005.  
  1006. junk = WIDGET_LABEL(c_row, VALUE = 'Current Char:')
  1007. cinfo_txt = WIDGET_TEXT(c_row, xsize = 36, ysize = 1, /FRAME, /EDIT, $
  1008.     UVALUE="CCODE")
  1009.  
  1010. c_row = WIDGET_BASE(wbases[1], /ROW)
  1011. junk = WIDGET_LABEL(c_row, VALUE = 'Position:')
  1012. cpos_txt = WIDGET_TEXT(c_row, xsize=8, ysize=1, /FRAME)
  1013.  
  1014. junk = WIDGET_LABEL(c_row, value= 'Width:')
  1015. cwidth_txt = WIDGET_TEXT(c_row, xsize=4, ysize= 1, /EDIT, /FRAME, $
  1016.     VALUE='16', UVALUE="WIDTH")
  1017. junk = WIDGET_LABEL(c_row, value= 'Offset:')
  1018. coff_txt = WIDGET_TEXT(c_row, xsize=4, ysize= 1, /EDIT, /FRAME, $
  1019.     VALUE='0', UVALUE="OFF")
  1020. junk = WIDGET_LABEL(c_row, value= 'Scale:')
  1021. cscale_txt = WIDGET_TEXT(c_row, xsize=6, ysize= 1, /EDIT, /FRAME, $
  1022.     VALUE='16', UVALUE="SCALE")
  1023.  
  1024. cdraw = WIDGET_DRAW(wbases[1], XSIZE = 640, YSIZE = 640, RETAIN=2,  $
  1025.     /BUTTON, /MOTION)
  1026.  
  1027. WIDGET_CONTROL, main_base, /REALIZE
  1028. WIDGET_CONTROL, cdraw, GET_VALUE = cwin
  1029. WIDGET_CONTROL, fdraw, GET_VALUE = fwin
  1030. WIDGET_CONTROL, wbases[1], MAP=0
  1031.  
  1032. refresh_pixmap = intarr(2)
  1033. for i=0,1 do begin        ;Make 2 backing pixmaps
  1034.     WINDOW, /free, /pix, xsize=640, ysize=640    ;Backing storage
  1035.     refresh_pixmap[i] = !d.window
  1036.     endfor
  1037.  
  1038. wset, fwin
  1039. draw_font
  1040. tek_color
  1041. wset, swin
  1042.  
  1043. XMANAGER, 'efont', main_base, EVENT_HANDLER = 'efont_event', $
  1044.     GROUP = group, /NO_BLOCK
  1045. end
  1046.